using System;
using System.Collections.Generic;
using System.Text;
using RS.DOM.Common;
using RS.DOM.Construction;

namespace RS.DOM.Types
{
    public class Area: Token
    {
        #region Constructors

        public Area(Context context, DocArea docArea)
            : base(context, docArea)
        {
            base.Text = "$";
            base.TokenType = TokenType.Area;
        }

        #endregion

        #region Properties

        public DocArea Result
        {
            get
            {
                return (DocArea)base.Result;
            }
        }

        #endregion

        #region Methods

        public override Token Operation(Token token, OperationType type)
        {
            if (type == OperationType.Agregate)
            {
                return this.Agregate(token);
            }
            else if (type == OperationType.Apply)
            {
                return this.Apply(token);
            }
            else if (type == OperationType.Point)
            {
                return this.Point(token);
            }
            else
            {
                return base.Operation(token, type);
            }
        }

        public Token Point(Token token)
        {
            Collection result = new Collection(this.Context);

            if (token.TokenType == TokenType.Number)
            {
                Area op1 = this;
                Number op2 = (Number)token;

                for (int i = 0; i < this.Result.Height; i++)
                {
                    result.Result.Add(new Number(this.Context, (int)op1.Result.GetItem(op2.Result, i).Value));
                }
            }

            return result;
        }

        public Token Apply(Token token)
        {
            if (token.TokenType == TokenType.Number)
            {
                Area op1 = this;
                Number op2 = (Number)token;

                op1.Result.Create(1, 1);
                DocItem item = new DocItem();
                item.Value = op2.Result;
                op1.Result.SetItem(0, 0, item);
            }
            else if (token.TokenType == TokenType.Collection)
            {
                Area op1 = this;
                Collection op2 = (Collection)token;

                op1.Result.Create(op2.Result.Count, 1);

                for (int i = 0; i < this.Result.Width; i++)
                {
                    DocItem item = new DocItem();
                    item.Value = op2.Result[i];
                    op1.Result.SetItem(i, 0, item);
                }
            }
            else if (token.TokenType == TokenType.Area)
            {
                Area op1 = this;
                Area op2 = (Area)token;

                op1.Result.Create(op2.Result.Width, op2.Result.Height);
                for (int i = 0; i < op2.Result.Width; i++)
                    for (int j = 0; j < op2.Result.Height; j++)
                    {
                        DocItem item = op2.Result.GetItem(i, j);
                        op1.Result.SetItem(i, j, item.Copy());
                    }
            }

            return this;
        }

        public Token Agregate(Token token)
        {
            Token result = null;

            if (token.TokenType == TokenType.Operator)
            {
                int value = 0;
                if (token.Text == "+")
                {
                    foreach (DocItem item in this.Result.Items)
                    {
                        value += (int)item.Value;
                    }
                }

                result = new Number(this.Context);
                result.Result = value;
            }

            return result;
        }

        #endregion
    }
}
